import json
import sys
import time

from machine import Pin
from umqtt.robust import MQTTClient

from buzzer import Buzzer
from led import Led
from mac import get_mac_address
from wifi import connect_wifi

RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 150, 0)
ORANGE = (255, 128, 0)
# 初始化LED对象，指定引脚为38
led = Led(Pin(38, Pin.OUT))
buzzer = Buzzer(48)
# WiFi配置
WIFI_SSID = "ST-Guest"
WIFI_PWD = "gstjk.02"
# WIFI_SSID = "RedwolfHome_29"
# WIFI_PWD = "operation0302@29601"
# MQTT配置
GID = "GID_DEMO"
MQTT_INSTANCE_ID = "mqtt-cn-m1e4h0bg003"
MQTT_BROKER = f"{MQTT_INSTANCE_ID}.mqtt.aliyuncs.com"  # 公共MQTT服务器（无需注册）
MQTT_PORT = 1883
# 生成唯一的MQTT客户端ID（前缀+MAC地址）
MQTT_CLIENT_ID = f"esp32_{get_mac_address()}"
ALIYUN_ACCESS_KEY = 'LTAI5tHZ1YCa1YzJxwcq6NQ9'
ALIYUN_MQTT_CLIENT_ID = f"{GID}@@@{MQTT_CLIENT_ID}"
ALIYUN_USER = f'Signature|{ALIYUN_ACCESS_KEY}|{MQTT_INSTANCE_ID}'
ALIYUN_PASSWORD = 'worGMEgLo4IQ0vxCdahhr0BJkEU='
MQTT_TOPIC_SUB = f"demo-esp32/p2p/{ALIYUN_MQTT_CLIENT_ID}"
MQTT_TOPIC_PUB = "demo-esp32/p2p/GID_DEMO@@@234567890"


# ------------------- MQTT消息处理 -------------------
def mqtt_callback(topic, msg):
    """
    {
  "cmd": "led",
  "r": 150,
  "g": 0,
  "b": 0,
  "brightness": 0.1
}
{
  "cmd": "buzzer",
  "frequency": 500,
  "duration": 0.2
}
    :param topic:
    :param msg:
    :return:
    """
    print(f"收到消息: 主题={topic.decode()}, 内容={msg.decode()}")
    try:
        payload = json.loads(msg.decode())
        print(payload)
        if payload["cmd"] == 'led':
            r = int(payload["r"])
            g = int(payload["g"])
            b = int(payload["b"])
            brightness = float(payload["brightness"])
            led.on(r, g, b, brightness)
            publish(MQTT_TOPIC_PUB, "led done")
        elif payload["cmd"] == 'buzzer':
            frequency = int(payload["frequency"])
            duration = float(payload["duration"])
            buzzer.beep(frequency, duration)
            publish(MQTT_TOPIC_PUB, "buzzer done")
        elif payload["cmd"] == 'play':
            # 定义一个简单的旋律（《小星星》片段）
            melody = [
                (523, 4), (523, 4), (587, 4), (587, 4),  # 1 1 2 2
                (659, 4), (659, 4), (587, 2),  # 3 3 2
                (523, 4), (523, 4), (587, 4), (587, 4),  # 1 1 2 2
                (659, 4), (659, 4), (587, 2)  # 3 3 2
            ]
            # 播放欢迎旋律
            buzzer.play_melody(melody, tempo=payload["tempo"])
            publish(MQTT_TOPIC_PUB, "play done")
        else:
            print(f"未知的命令: {payload.cmd}")
    except Exception as e:
        print(f"消息处理失败: {e}")


mqtt_client = None


def publish(topic, msg):
    if mqtt_client:
        try:
            mqtt_client.publish(topic, msg, qos=1)
            print(f"已发布消息: 主题={topic}, 内容={msg}")
        except Exception as e:
            print(f"消息发布失败: {e}")
    else:
        print("MQTT客户端未连接，无法发布消息")


# ------------------- MQTT连接 -------------------
def connect_mqtt():
    global mqtt_client
    mqtt_client = MQTTClient(
        client_id=ALIYUN_MQTT_CLIENT_ID,
        server=MQTT_BROKER,
        port=MQTT_PORT,
        keepalive=60,
        user=ALIYUN_USER,
        password=ALIYUN_PASSWORD,
    )

    mqtt_client.set_callback(mqtt_callback)
    try:
        print(f"开始连接MQTT服务器: {MQTT_BROKER}，客户端ID: {ALIYUN_MQTT_CLIENT_ID}")
        mqtt_client.connect(clean_session=True)
        print(f"已连接MQTT服务器: {MQTT_BROKER}，客户端ID: {ALIYUN_MQTT_CLIENT_ID}")
        return True
    except Exception as e:
        print(json.dumps(e))
        print(f"MQTT连接失败: {e}")
        return False


if __name__ == "__main__":
    led.on(*ORANGE, brightness=0.1)
    if not connect_wifi(WIFI_SSID, WIFI_PWD):
        led.on(*RED, brightness=0.1)
        sys.exit(1)
    buzzer.beep(1000, 0.2)
    print("CLIENT ID: %s" % ALIYUN_MQTT_CLIENT_ID)
    time.sleep(1)
    if not connect_mqtt():
        led.on(*RED, brightness=0.1)
        sys.exit(1)
    led.on(*GREEN, brightness=0.1)
    print("开始监听MQTT消息...")
    try:
        while True:
            # umqtt.robust 的 check_msg() 会自动处理重连
            mqtt_client.check_msg()
            time.sleep(0.1)
    except KeyboardInterrupt:
        print("程序被中断")
    except Exception as e:
        print(f"程序运行异常: {e}")
    finally:
        try:
            if mqtt_client:
                mqtt_client.disconnect()
        except:
            pass
        print("资源已释放，程序退出")
